#include "playthread.h"

bool endOfMusic;

void __stdcall syncFunc(HSYNC handle, DWORD channel, DWORD data, void *user)
{
    //BASS_ChannelRemoveSync(channel, handle);
    BASS_ChannelStop(channel);
    qDebug() << "End of playback!";
    //emit endOfPlayback();
   // endOfMusic = true;
}

AudioThread::AudioThread(QObject *parent) :
    QObject(parent)
{
    t = new QTimer(this);
    connect(t, SIGNAL(timeout()), this, SLOT(signalUpdate()));
    endOfMusic = true;
    v = 1.0;
}

bool AudioThread::play(QString filename)
{
    BASS_ChannelStop(chan);
    if (!(chan = BASS_StreamCreateFile(false, filename.toLocal8Bit().data(), 0, 0,  BASS_STREAM_DECODE))){
           qDebug() << "Can't play file1";
           return false;
    }
    if (!(chan=BASS_FX_TempoCreate(chan, BASS_FX_FREESOURCE)))
    {
        qDebug() << "Can't play file2";
        return false;
    }
    if (!(exportChan = BASS_StreamCreateFile(false, filename.toLocal8Bit().data(), 0, 0,  BASS_STREAM_DECODE))){
           qDebug() << "Can't play file3";
           return false;
    }
    if (!(exportChan=BASS_FX_TempoCreate(exportChan, BASS_FX_FREESOURCE | BASS_STREAM_DECODE)))
    {
        qDebug() << "Can't play file4";
        return false;
    }
        endOfMusic = false;
        BASS_ChannelPlay(chan, true);
        t->start(100);
        BASS_ChannelSetSync(chan, BASS_SYNC_END, 0, &syncFunc, 0);
        playing = true;
    return true;
}

void AudioThread::pause()
{
    BASS_ChannelPause(chan);
    t->stop();
    playing = false;
}

void AudioThread::resume()
{
    endOfMusic = false;
    if (!BASS_ChannelPlay(chan, false))
        qDebug() << "Error resuming";
    else
    {
        t->start(98);
        playing = true;
    }

}

void AudioThread::stop()
{
    BASS_ChannelStop(chan);

    changePosition(0);
    t->stop();
    playing = false;
    signalUpdate();
}

void AudioThread::signalUpdate()
{
    double cur = BASS_ChannelBytes2Seconds(chan, BASS_ChannelGetPosition(chan, BASS_POS_BYTE));
    double len =  BASS_ChannelBytes2Seconds(chan, BASS_ChannelGetLength(chan, BASS_POS_BYTE));
    if (len - cur <= 1.0)
        pause();
    if (endOfMusic == false)
    {
        emit curPos(cur, len);
    }
    else
    {
        //emit endOfPlayback();
        pause();
    }
}

void AudioThread::changePosition(int position)
{
    if ((int)BASS_ChannelBytes2Seconds(chan, BASS_ChannelGetLength(chan, BASS_POS_BYTE)) - position > 1.0 )
        BASS_ChannelSetPosition(chan, BASS_ChannelSeconds2Bytes(chan, position), BASS_POS_BYTE);
    else
        BASS_ChannelSetPosition(chan, BASS_ChannelSeconds2Bytes(chan, getLen() - 1), BASS_POS_BYTE);
}

int AudioThread::getLen()
{
    QWORD len=BASS_ChannelGetLength(chan, BASS_POS_BYTE); // the length in bytes
    return BASS_ChannelBytes2Seconds(chan, len); // the length in seconds
}

void AudioThread::check(bool vol)
{
    if (vol) {
        BASS_ChannelSetAttribute(chan, BASS_ATTRIB_VOL, v);
        BASS_ChannelSetAttribute(exportChan, BASS_ATTRIB_VOL, v);
    }
    else {
        BASS_ChannelSetAttribute(chan, BASS_ATTRIB_VOL, 0);
        BASS_ChannelSetAttribute(exportChan, BASS_ATTRIB_VOL, 0);
    }

}

void AudioThread::volume(int value)
{
    v = float(value) / 100;
    BASS_ChannelSetAttribute(chan, BASS_ATTRIB_VOL, v);
    BASS_ChannelSetAttribute(exportChan, BASS_ATTRIB_VOL, v);
}

void AudioThread::leftRight(int value)
{
    BASS_ChannelSetAttribute(chan,BASS_ATTRIB_PAN, float(value) / 100);
    BASS_ChannelSetAttribute(exportChan,BASS_ATTRIB_PAN, float(value) / 100);
}

void AudioThread::del_effects()
{
    for (int i = 0; i < list_effects.size(); i++) {
        if (!BASS_ChannelRemoveFX(chan, list_effects[i]))
            qDebug() << "error delete effects "<<QString::number(BASS_ErrorGetCode());
        BASS_ChannelRemoveFX(exportChan, list_effects[i]);
    }
    list_effects.clear();
}

void AudioThread::addAttribute(DWORD type, float value)
{
        BASS_ChannelSetAttribute(chan, type, 0);
        BASS_ChannelSetAttribute(exportChan, type, 0);


    if (!BASS_ChannelSetAttribute(chan, type, value))
        qDebug() << "value = " <<QString::number(value)<<"error added effects "<<QString::number(BASS_ErrorGetCode());
    if (!BASS_ChannelSetAttribute(exportChan, type, value))
        qDebug() << "value = " <<QString::number(value)<<"error added effects "<<QString::number(BASS_ErrorGetCode());
}

HSTREAM AudioThread::getChannel()
{
    return exportChan;
}

void AudioThread::del()
{
    emit delTrack(this);
    BASS_ChannelStop(chan);
    endOfMusic = true;
}

void AudioThread::addFX(DWORD type, const void* params)
{
    HFX fx = BASS_ChannelSetFX(chan, type, 0);
    if(BASS_FXSetParameters(fx, params))
    {}
    else
        qDebug() << "error added effects "<<QString::number(BASS_ErrorGetCode());
     list_effects.push_back(fx);
    fx = BASS_ChannelSetFX(exportChan, type, 0);
    BASS_FXSetParameters(fx, params);
}
